package com.JFapp.service.impl;

import com.JFapp.constants.SystemConstants;
import com.JFapp.domain.entity.*;
import com.JFapp.domain.vo.PageVo;
import com.JFapp.domain.vo.PerformanceSumVo;
import com.JFapp.domain.vo.PerformanceVo;
import com.JFapp.eumns.AppHttpCodeEnum;
import com.JFapp.exception.SystemException;
import com.JFapp.mapper.PerformanceMapper;
import com.JFapp.service.PerformanceService;
import com.JFapp.service.UserService;
import com.JFapp.utils.BeanCopyUtils;
import com.JFapp.utils.RedisCache;
import com.JFapp.utils.SecurityUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;


/**
 * 绩效表(Performance)表服务实现类
 *
 * @author makejava
 * @since 2024-02-20 19:46:21
 */
@Service("performanceService")
public class PerformanceServiceImpl extends ServiceImpl<PerformanceMapper, Performance> implements PerformanceService {


    @Autowired
    private UserService userService;

    @Autowired
    private RedisCache redisCache;
    @Override
    @ApiOperation("查询个人绩效")
    public ResponseResult selectPerformanceByUid(Integer pageNum, Integer pageSize) {
        Long userId = SecurityUtils.getUserId();
        LambdaQueryWrapper<Performance> wrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<Performance> wrapper1 = wrapper.eq(Performance::getUserId, userId).eq(Performance::getPerformanceStatus,SystemConstants.PERFORMANCE_STATUE);
        List<Performance> list = list(wrapper);
        Page<Performance> performancePage= new Page<>(pageNum,pageSize);
        page(performancePage,wrapper1);
        List<Performance> performances = performancePage.getRecords();

        Integer performanceSum = list.stream()
                .filter(performance -> performance.getPerformanceStatus() == SystemConstants.PERFORMANCE_STATUE)
                .map(performance -> performance.getPerformancePrice())
                .reduce(0,Integer::sum);

        List<PerformanceVo> performancesVo = BeanCopyUtils.copyBeanList(performances, PerformanceVo.class);

        Map<Long,String> userNames=userService.getIdAndNameById(
                performancesVo.stream()
                .map(performance -> performance.getPerformanceGiver())
                .collect(Collectors.toList()));
        List<PerformanceVo> performanceVoList = performancesVo.stream()
                .peek(performanceVo -> {
                    Long uid = performanceVo.getPerformanceGiver(); // 获取PerformanceVo对象中的giverId
                    Optional<String> optionalUserName = Optional.ofNullable(userNames.get(uid)); // 尝试从userNames Map中获取对应的userName
                    optionalUserName.ifPresent(userName -> performanceVo.setPerformanceGiverName(userName));
                })
                .collect(Collectors.toList());

        PageVo pageVo =new PageVo(performanceVoList,performancePage.getTotal());

        PerformanceSumVo performanceVo = new PerformanceSumVo(performanceSum,pageVo);
        return ResponseResult.okResult(performanceVo);
    }

    @Override
    public ResponseResult selectRanking(Long start, Long end) {
        Set<ZSetOperations.TypedTuple<String>> zSet;
        if (start>=1l) {
            zSet = redisCache.getCacheZSet(SystemConstants.PERFORMANCE_RANK, start - 1, end-1);
        } else {
            throw new SystemException(AppHttpCodeEnum.RANK_START_ERROR);
        }
        return ResponseResult.okResult(zSet);
    }

    @Override
    @ApiOperation("新增绩效记录")
    public void addRecords(Repair repair) {
        User user = userService.getByName(repair.getReceiver());
        Performance performance=new Performance();
        synchronized (performance) {
            performance.setUserId(user.getId());
            performance.setPerformancePrice(repair.getPerformancePrice());
            performance.setPerformanceGiver(repair.getCreateId());
            performance.setPerformanceStatus(SystemConstants.PERFORMANCE_STATUE);
            performance.setPerformanceContent(SystemConstants.FINISH_REPAIR);
            save(performance);
        }
    }

    @Override
    @ApiOperation("绩效变动申请")
    public ResponseResult changePerformance(PerformanceVo performanceVo) {
        Performance performance= BeanCopyUtils.copyBean(performanceVo, Performance.class);
        performance.setUserId(userService.selectID(performanceVo.getUserName()));
        performance.setPerformanceGiver(SecurityUtils.getUserId());
        save(performance);
        return ResponseResult.okResult();
    }

    @Override
    public ResponseResult getAuditPerformance(Integer pageNum, Integer pageSize) {
        LambdaQueryWrapper<Performance> wrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<Performance> wrapper1 = wrapper.eq(Performance::getPerformanceStatus,SystemConstants.PERFORMANCE_STATUE_DEFAULT);
        return getResponseResult(pageNum, pageSize, wrapper1);
    }

    @Override
    public ResponseResult selectPerformanceByName(String userName, Integer pageNum, Integer pageSize) {
        Long id = userService.selectID(userName);
        LambdaQueryWrapper<Performance> queryWrapper=new LambdaQueryWrapper<>();
        LambdaQueryWrapper<Performance> wrapper = queryWrapper.select().eq(Performance::getUserId, id)
                .eq(Performance::getPerformanceStatus, SystemConstants.PERFORMANCE_STATUE);
        return getResponseResult(pageNum, pageSize, wrapper);
    }

    @Override
    public ResponseResult getAuditPerformanceByUserId(Integer pageNum, Integer pageSize) {
        Long userId = SecurityUtils.getUserId();
        LambdaQueryWrapper<Performance> wrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<Performance> wrapper1 = wrapper
                .eq(Performance::getPerformanceStatus,SystemConstants.PERFORMANCE_STATUE_DEFAULT)
                .eq(Performance::getPerformanceGiver,userId);
        return getResponseResult(pageNum, pageSize, wrapper1);
    }

    @Override
    public ResponseResult deleteAuditPerformance(Long performanceId) {
        LambdaQueryWrapper<Performance> queryWrapper=new LambdaQueryWrapper<>();
        Performance performance = getOne(queryWrapper.eq(Performance::getPerformanceId, performanceId));
        if (performance.getPerformanceStatus()==SystemConstants.PERFORMANCE_STATUE_DEFAULT&&performance.getPerformanceGiver()==SecurityUtils.getUserId()){
            baseMapper.delete(queryWrapper.eq(Performance::getPerformanceId, performanceId));
            return ResponseResult.okResult();
        }else {
            throw  new SystemException(AppHttpCodeEnum.NO_OPERATOR_AUTH);
        }
    }

    @Override
    public ResponseResult updateChangePerformance(PerformanceVo performanceVo) {
        Performance performance = BeanCopyUtils.copyBean(performanceVo, Performance.class);
        LambdaUpdateWrapper<Performance> updateWrapper=new LambdaUpdateWrapper<>();
        LambdaUpdateWrapper<Performance> wrapper = updateWrapper.eq(Performance::getPerformanceId, performance.getPerformanceId());
        update(performance,wrapper);
        return ResponseResult.okResult();
    }

    private ResponseResult getResponseResult(Integer pageNum, Integer pageSize, LambdaQueryWrapper<Performance> wrapper) {
        Page<Performance> performancePage= new Page<>(pageNum,pageSize);
        page(performancePage,wrapper);
        List<Performance> performances = performancePage.getRecords();
        List<PerformanceVo> performanceList = BeanCopyUtils.copyBeanList(performances, PerformanceVo.class);
        List<Long> userIds = performanceList.stream()
                .map(performanceVo -> performanceVo.getUserId())
                .collect(Collectors.toList());
        Map<Long,String> userNames=userService.getIdAndNameById(userIds);
        List<PerformanceVo> performanceVoList = performanceList.stream()
                .peek(performanceVo -> {
                    Long userId = performanceVo.getUserId(); // 获取PerformanceVo对象中的userId
                    Optional<String> optionalUserName = Optional.ofNullable(userNames.get(userId)); // 尝试从userNames Map中获取对应的userName
                    optionalUserName.ifPresent(userName -> performanceVo.setUserName(userName));
                })
                .collect(Collectors.toList());
//        IntStream.range(0,performanceList.size())
//                .forEach(i -> performanceList.get(i).setUserName(userNames.get(i)));
        PageVo pageVo =new PageVo(performanceVoList,performancePage.getTotal());
        return ResponseResult.okResult(pageVo);
    }

    @Override
    @ApiOperation("审核申请")
    public ResponseResult changePerformanceAudit(Performance performance, Integer audit) {

        if (performance.getPerformanceStatus()==SystemConstants.PERFORMANCE_STATUE_DEFAULT){
            if (audit==SystemConstants.AGREE) {
                User user = userService.getById(performance.getUserId());
                LambdaUpdateWrapper<Performance> updateWrapper=new LambdaUpdateWrapper<>();
                LambdaUpdateWrapper<Performance> wrapper = updateWrapper.set(Performance::getPerformanceStatus, SystemConstants.PERFORMANCE_STATUE)
                        .eq(Performance::getPerformanceId, performance.getPerformanceId());
                update(wrapper);
                redisCache.updateZSet(SystemConstants.PERFORMANCE_RANK,user.getUserName(),performance.getPerformancePrice().doubleValue());
            } else if (audit==SystemConstants.REFUSE) {
                LambdaUpdateWrapper<Performance> updateWrapper=new LambdaUpdateWrapper<>();
                LambdaUpdateWrapper<Performance> wrapper = updateWrapper.set(Performance::getPerformanceStatus, SystemConstants.PERFORMANCE_STATUE_INVALIDATION)
                        .eq(Performance::getPerformanceId, performance.getPerformanceId());
                update(wrapper);
            }
        }else {
            throw new SystemException(AppHttpCodeEnum.IDEMPOTENT);
        }
        return ResponseResult.okResult();
    }



    @Scheduled(cron = "0 0 1 * * ?") //每日一点触发
    public void updateRankingToRedis(){
        Set<Ranking> ranking=baseMapper.selectRanking();
        redisCache.redisTemplate.delete(SystemConstants.PERFORMANCE_RANK);
        Set<ZSetOperations.TypedTuple<String>> typedTuples = ranking.stream()
                .map(ranking1 -> new DefaultTypedTuple<>(ranking1.getUserName(), ranking1.getPerformanceSum()))
                .collect(Collectors.toSet());
        redisCache.setCacheZSet(SystemConstants.PERFORMANCE_RANK,typedTuples);
    }




}
